home *** CD-ROM | disk | FTP | other *** search
- /* Spreadsheet functions for SSS */
- /* Tue,30 Jul 1991 */
- /* Copyright C.T.Stretch 1991 */
-
- #include "ssshdr.h"
-
- #define YESNULL 0
-
- entry **sheet;
- wimp_w swind;
- int dispwidth;
- int nrows,ncols,width[NCOLS];
- int sx0=0,sx1=0,sy0=0,sy1=0;
- int ex0,ex1,ey0,ey1;
- int bx0=0,by1=LINEHT,bw=INITWIDTH*CHWIDTH,bh=LINEHT;
- int ebx0=0,eby1=LINEHT,ebw=INITWIDTH*CHWIDTH,ebh=LINEHT;
- char buf[BUFLEN+16],fname[BUFLEN];
- int uy;
- BOOL autox,changed,fixed;
- int prwidth=80;
- BOOL repfirst=FALSE;
- BOOL mono=FALSE;
- char sep[4]=",";
- static int tempsize;
-
- void sheet_change()
- { uy=0;changed=FALSE;
- event_setmask(YESNULL);
- }
-
- void sheet_box()
- { int x,bx,by,more;
- int cx0=bx0,cw=bw,cy1=by1,ch=bh;
- wimp_redrawstr r[1];
- r->w=swind;
- r->box.x0=0;r->box.y1=0;
- r->box.x1=dispwidth;r->box.y0=-LINEHT*nrows;
- bx0=0;bw=0;
- for(x=0;x<NCOLS;x++)
- { if(x>=sx0) break;
- bx0+=width[x]*CHWIDTH;
- }
- for(;x<NCOLS;x++)
- { bw+=width[x]*CHWIDTH;
- if(x>=sx1) break;
- }
- by1=(sy1+1)*LINEHT;
- bh=(sy1-sy0+1)*LINEHT;
- wimpt_noerr(wimp_update_wind(r,&more));
- bx=r->box.x0-r->scx;
- by=r->box.y1-r->scy;
- while(more)
- { wimp_setcolour(15+16*3);
- bbc_rectanglefill(bx+bx0,by-by1,bw,bh);
- bbc_rectanglefill(bx+bx0+8,by-by1+8,bw-16,bh-16);
- bbc_rectanglefill(bx+cx0,by-cy1,cw,ch);
- bbc_rectanglefill(bx+cx0+8,by-cy1+8,cw-16,ch-16);
- wimp_get_rectangle(r,&more);
- }
- }
-
- void sheet_ebox()
- { int x,bx,by,more;
- int cx0=ebx0,cw=ebw,cy1=eby1,ch=ebh;
- wimp_redrawstr r[1];
- r->w=swind;
- r->box.x0=0;r->box.y1=0;
- r->box.x1=dispwidth;r->box.y0=-LINEHT*nrows;
- ebx0=0;ebw=0;
- for(x=0;x<NCOLS;x++)
- { if(x>=ex0) break;
- ebx0+=width[x]*CHWIDTH;
- }
- for(;x<NCOLS;x++)
- { ebw+=width[x]*CHWIDTH;
- if(x>=ex1) break;
- }
- eby1=(ey1+1)*LINEHT;
- ebh=(ey1-ey0+1)*LINEHT;
- wimpt_noerr(wimp_update_wind(r,&more));
- bx=r->box.x0-r->scx;
- by=r->box.y1-r->scy;
- while(more)
- { wimp_setcolour(12+16*3);
- bbc_rectanglefill(bx+ebx0,by-eby1,ebw,ebh);
- bbc_rectanglefill(bx+cx0,by-cy1,cw,ch);
- wimp_get_rectangle(r,&more);
- }
- }
-
- void sheet_home()
- { ex0=ex1=0;
- ey0=ey1=0;
- sx0=sy0=0;
- sx1=sy1=0;
- sheet_box();
- sheet_ebox();
- }
-
- BOOL sheet_init()
- { int i;
- nrows=INITNROWS;
- ncols=INITNCOLS;
- if(!flex_alloc((flex_ptr)&sheet,4*NCOLS*nrows)) return FALSE;
- for(i=0;i<nrows*NCOLS;i++) sheet[i]=0;
- for(i=0;i<NCOLS;i++) width[i]=INITWIDTH;
- strcpy(fname,"Sheet");
- return TRUE;
- }
-
- void sheet_clear(int nr)
- { int i;
- visdelay_begin();
- for(i=0;i<nrows*NCOLS;i++) if(sheet[i]) flex_free((flex_ptr)(sheet+i));
- nrows=nr;
- if(!flex_extend((flex_ptr)&sheet,4*NCOLS*nrows)) werr(1,"No room");
- for(i=0;i<nrows*NCOLS;i++) sheet[i]=0;
- for(i=0;i<NCOLS;i++) width[i]=INITWIDTH;
- visdelay_end();
- }
-
- void sheet_getentry(int x,int y,int t)
- { entry **cb=sheet+x+y*NCOLS;
- int len=strlen(buf)+13;
- for(expr=buf;*expr==' ';expr++);
- if(!(*expr))
- { if(*cb) flex_free((flex_ptr)cb);
- *cb=0;
- return;
- }
- if(!((*cb)?flex_extend((flex_ptr)cb,len):flex_alloc((flex_ptr)cb,len)))
- { werr(0,"Out of memory");return;}
- *((int *)(*cb))=t;
- strcpy(&((*cb)->c),buf);
- if(t>=FINT)
- { vx=x;vy=y;expr=buf;
- eval();
- (*cb)->v=value;
- (*cb)->a=(errno!=0);
- (*cb)->p=(perr!=0);
- (*cb)->u=fixed;
- }
- }
-
- void sheet_update()
- { entry *cb;
- int ux;
- for(ux=0;ux<ncols;ux++)
- { cb=sheet[ux+uy*NCOLS];
- if(!cb) continue;
- if(cb->u) continue;
- if(cb->t<FINT) continue;
- if(cb->p) continue;
- vx=ux;vy=uy;expr=&(cb->c);
- eval();
- if(cb->v!=value)
- { changed=TRUE;
- cb->v=value;
- }
- if(cb->a!=(errno!=0))
- { changed=TRUE;
- cb->a=(errno!=0);
- }
- }
- }
-
- static void clear(int x,int y)
- { entry **ce=sheet+x+y*NCOLS;
- if(*ce)
- { flex_free((flex_ptr)ce);
- *ce=0;
- }
- }
-
- static void copy(int xs,int ys,int xt,int yt)
- { entry **es=sheet+xs+ys*NCOLS,**et=sheet+xt+yt*NCOLS;
- int len;
- if(*es)
- { len=flex_size((flex_ptr)es);
- if(!((*et)?flex_extend((flex_ptr)et,len):flex_alloc((flex_ptr)et,len)))
- { werr(0,"Out of memory");return;}
- memcpy((char*)*et,(char*)*es,len);
- }
- else if(*et)
- { flex_free((flex_ptr)et);
- *et=0;
- }
- }
-
- void sheet_newrow(void)
- { int x,y;
- if(!flex_extend((flex_ptr)&sheet,4*NCOLS*(nrows+1))) return;
- for(x=0;x<NCOLS;x++) sheet[x+nrows*NCOLS]=0;
- for(y=nrows;y>ey0;y--) for(x=0;x<ncols;x++) copy(x,y-1,x,y);
- for(x=0;x<ncols;x++) clear(x,ey0);
- nrows++;
- if(autox) sheet_change();
- }
-
- void sheet_newcol(void)
- { int x,y;
- if(ncols>=NCOLS) return;
- for(x=ncols;x>ex0;x--) for(y=0;y<nrows;y++) copy(x-1,y,x,y);
- for(y=0;y<nrows;y++) clear(ex0,y);
- ncols++;
- if(autox) sheet_change();
- }
-
- void sheet_delrow(void)
- { int x,y,d=ey1-ey0+1;
- visdelay_begin();
- for(x=0;x<ncols;x++)
- { for(y=ey1+1;y<nrows;y++) copy(x,y,x,y-d);
- for(y=nrows-d;y<nrows;y++) clear(x,y);
- }
- nrows-=d;if(nrows<1) nrows=1;
- flex_extend((flex_ptr)&sheet,4*NCOLS*nrows);
- if(autox) sheet_change();
- visdelay_end();
- }
-
- void sheet_delcol(void)
- { int x,y,d=ex1-ex0+1;
- visdelay_begin();
- for(y=0;y<nrows;y++)
- { for(x=ex1+1;x<ncols;x++) copy(x,y,x-d,y);
- for(x=ncols-d;x<ncols;x++) clear(x,y);
- }
- ncols-=d;
- if(ncols<1) ncols=1;
- if(autox) sheet_change();
- visdelay_end();
- }
-
-
- void sheet_bcopy(void)
- { int x,y,tx,ty;
- if((ex0==ex1)&&(ey0==ey1))
- { for(y=sy0;y<=sy1;y++) for(x=sx0;x<=sx1;x++)
- if((x+ex0-sx0<ncols)&&(y+ey0-sy0<nrows)) copy(x,y,x+ex0-sx0,y+ey0-sy0);
- }
- else
- { tx=ex0;ty=ey0;
- for(y=sy0;y<=sy1;y++) for(x=sx0;x<=sx1;x++)
- { if(tx>ex1) {tx=ex0;ty++;}
- if(ty>ey1) return;
- copy(x,y,tx,ty);
- tx++;
- }
- }
- if(autox) sheet_change();
- }
-
- static int numcmp(const void *s,const void *t)
- { double a,b;
- a=sheet[(*(int*)s)*NCOLS+sx0]->v;
- b=sheet[(*(int*)t)*NCOLS+sx0]->v;
- if(a<b) return -1;
- return (a>b)?1:0;
- }
-
- static int textcmp(const void *s,const void *t)
- { char *a,*b;
- a=&(sheet[(*(int*)s)*NCOLS+sx0]->c);
- b=&(sheet[(*(int*)t)*NCOLS+sx0]->c);
- return strcmp(a,b);
- }
-
- static int numcmpr(const void *s,const void *t)
- { double a,b;
- a=sheet[(*(int*)s)+sy0*NCOLS]->v;
- b=sheet[(*(int*)t)+sy0*NCOLS]->v;
- if(a<b) return -1;
- return (a>b)?1:0;
- }
-
- static int textcmpr(const void *s,const void *t)
- { char *a,*b;
- a=&(sheet[(*(int*)s)+sy0*NCOLS]->c);
- b=&(sheet[(*(int*)t)+sy0*NCOLS]->c);
- return strcmp(a,b);
- }
-
- static void temps(int x,int y)
- { entry **e=sheet+x+y*NCOLS;
- if(*e)
- { tempsize=flex_size((flex_ptr)e);
- memcpy(buf,(char*)(*e),tempsize);
- }
- else tempsize=0;
- }
-
- static void tempr(int x,int y)
- { entry **e=sheet+x+y*NCOLS;
- if(tempsize)
- { if(flex_extend((flex_ptr)e,tempsize)) memcpy((char*)(*e),buf,tempsize);
- }
- else if(e) flex_free((flex_ptr)e);
- }
-
- static void sortcol()
- { int x,y,z,n=sy1-sy0+1;
- int *p,*q;
- entry *e=sheet[sx0+sy0*NCOLS];
- if(!e) return;
- if((sy0!=ey0)||(sy1!=ey1))return;
- if(!flex_alloc((flex_ptr)&p,4*n)) return;
- if(!flex_alloc((flex_ptr)&q,4*n)) return;
- for(y=0;y<n;y++) p[y]=sy0+y;
- if(e->t<FINT)
- { for(y=sy0;y<=sy1;y++)
- { e=sheet[sx0+y*NCOLS];
- if(!e) goto done;
- if(e->t>=FINT) goto done;
- }
- qsort((void*)p,n,4,textcmp);
- }
- else
- { for(y=sy0;y<=sy1;y++)
- { e=sheet[sx0+y*NCOLS];
- if(!e) goto done;
- if((e->t<FINT)||(e->a)||(e->p)) goto done;
- }
- qsort((void*)p,n,4,numcmp);
- }
- for(x=ex0;x<=ex1;x++)
- { for(y=0;y<n;y++) q[y]=TRUE;
- for(y=0;y<n;y++) if((q[y])&&(p[y]!=y+sy0))
- { temps(x,y+sy0);
- for(z=y;p[z]!=y+sy0;z=p[z]-sy0)
- { copy(x,p[z],x,z+sy0);
- q[p[z]-sy0]=FALSE;
- }
- tempr(x,z+sy0);
- }
- }
- done:flex_free((flex_ptr)&p);
- flex_free((flex_ptr)&q);
- }
-
- static void sortrow()
- { int x,y,z,n=sx1-sx0+1;
- int *p,*q;
- entry *e=sheet[sx0+sy0*NCOLS];
- if(!e) return;
- if((sx0!=ex0)||(sx1!=ex1))return;
- if(!flex_alloc((flex_ptr)&p,4*n)) return;
- if(!flex_alloc((flex_ptr)&q,4*n)) return;
- for(x=0;x<n;x++) p[x]=sx0+x;
- if(e->t<FINT)
- { for(x=sx0;x<=sx1;x++)
- { e=sheet[x+sy0*NCOLS];
- if(!e) goto done;
- if(e->t>=FINT) goto done;
- }
- qsort((void*)p,n,4,textcmpr);
- }
- else
- { for(x=sx0;x<=sx1;x++)
- { e=sheet[x+sy0*NCOLS];
- if(!e) goto done;
- if((e->t<FINT)||(e->a)||(e->p)) goto done;
- }
- qsort((void*)p,n,4,numcmpr);
- }
- for(y=ey0;y<=ey1;y++)
- { for(x=0;x<n;x++) q[x]=TRUE;
- for(x=0;x<n;x++) if((q[x])&&(p[x]!=x+sx0))
- { temps(x+sx0,y);
- for(z=x;p[z]!=x+sx0;z=p[z]-sx0)
- { copy(p[z],y,z+sx0,y);
- q[p[z]-sx0]=FALSE;
- }
- tempr(z+sx0,y);
- }
- }
- done:flex_free((flex_ptr)&p);
- flex_free((flex_ptr)&q);
- }
-
- void sheet_sort(void)
- { if(sx0==sx1) sortcol();
- else if(sy0==sy1) sortrow();
- if(autox) sheet_change();
- }
-